#include <iostream>
#include <string>
#include <unistd.h>
#include <wait.h>
#include <cstdlib>
#include <vector>
#include<time.h>
#include"task.hpp"
using namespace std;

enum
{
    UsageError = 1,
    ArgError,
    PipeError
};

void Usage(const string &proc)
{
    cout << "Usage: " << proc << " subprocess-num" << endl;
}

class Channel
{
public:
    Channel(const string &name, pid_t id, int wfd)
        : _name(name), _subprocess_id(id), _wfd(wfd)
    {
    }
    ~Channel()
    {
    }
    void PrintDebug()
    {
        cout << "_name:" << _name;
        cout << " _subprocess_id:" << _subprocess_id;
        cout << " _wfd:" << _wfd << endl;
    }
    string name()
    {
       return _name;       
    }
    int wfd()
    {
        return _wfd;
    }
    pid_t subprocess_id()
    {
        return _subprocess_id;
    }
private:
    string _name;
    pid_t _subprocess_id; // 相对应的子进程id
    int _wfd;             // 写端
};

class Processpool
{
public:
    Processpool(int sub_process_num)
        : _sub_process_num(sub_process_num)
    {
    }
    ~Processpool()
    {
    }
    int CreaterProcess(work_t work)
    {
        for (int number = 0; number < _sub_process_num; number++)
        {
            // 管道
            int pipefd[2]{0};
            int n = pipe(pipefd);
            if (n < 0)
                return PipeError;
            pid_t id = fork();
            if (id == 0) // 子进程 读
            {
                close(pipefd[1]);
                //执行任务
                dup2(pipefd[0],0);
                work();
                exit(0);
            }
            // 父进程
            string cname = "channel-" + to_string(number);
            close(pipefd[0]);
            channels.push_back(Channel(cname, id, pipefd[1]));
        }
        return 0;
    }
    // 2.控制子进程
    void Debug()
    {
        for (auto &channel : channels)
        {
            channel.PrintDebug();
        }
    }
    int nextchannel()
    {
        static int next=0;
        int c=next++;
        next%=channels.size();
        return c;
    }

    void SendTaskCode(int index,uint32_t code)
    {
        cout<<"send code: "<<code<<"to "<<channels[index].name()<<"sub_process_id: "<<channels[index].subprocess_id()<<endl;
        write(channels[index].wfd(),&code,sizeof(code));
    }
private:
    int _sub_process_num;
    vector<Channel> channels;
};

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        return 1;
    }
    int sub_process_num = stoi(argv[1]);
    if (sub_process_num <= 0)
        return ArgError;

    srand((uint64_t)time(nullptr));

    // 1.创建管道通信和子进程
    Processpool *processpool_ptr = new Processpool(sub_process_num);
    processpool_ptr->CreaterProcess(worker);

    // 2.控制子进程
    while (true)
    {
        //1.选择进程和通道
        int channel=processpool_ptr->nextchannel();
        //sleep(1);
        //cout<<channel.name()<<endl;

        //2.选择一个任务
        uint32_t code=Nexttask();

        //3.向指定管道发送任务
        processpool_ptr->SendTaskCode(channel,code);
        sleep(1);
    }
    
    sleep(100);
    // 3.回收子进程
    wait(NULL);
    return 0;
}
